#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>

void ConvInt8to32_8x4(int *dst, char *input, char *weight, size_t src_depth, size_t dst_step, size_t dst_depth);
void ConvInt8(char *input, char *weight, int *output, int *bias, int step, int depth, int offset);

void main()
{
    int iw = 32;
    int ih = 32;
    int ic = 32;
    int oc = 4;
    int kw = 4;
    int kh = 4;
    int ow = 32;
    int oh = 32;

    int packed_input_size = ow *oh * 16 * kw * kh * ic;
    char *packed_input_1 = (char *) malloc(packed_input_size * sizeof(char));
    char *packed_input_2 = (char *) malloc(packed_input_size * sizeof(char));
    for (int i = 0; i < packed_input_size; ++i) {
        packed_input_1[i] = i % 10;
        packed_input_2[i] = packed_input_1[i];
    }

    int packed_weight_size = oc * kw * kh * ic;
    char *packed_weight_1 = (char *) malloc(packed_weight_size * sizeof(char));
    char *packed_weight_2 = (char *) malloc(packed_weight_size * sizeof(char));
    for (int i = 0; i < packed_weight_size; ++i) {
        packed_weight_1[i] = i % 5 + 2;
        packed_weight_2[i] = packed_weight_1[i];
    }

    int out_size = 24 * ow * oh * oc;
    int *output = (int *) malloc(out_size * sizeof(int));
    memset(output, 0, out_size * sizeof(int));

    int *summer = (int *) malloc(out_size * sizeof(int));
    memset(summer, 0, out_size * sizeof(int));

    struct timeval start, end;
    double duration = 0;
    gettimeofday(&start, NULL);
    for (int i = 0; i < ow * oh / 2; i++) {
        ConvInt8to32_8x4(output, packed_input_1 + i * kw * kh * 4, packed_weight_1, summer, kw*kh*ic / 16, 4 * 4 * sizeof(int), oc / 4);
    }
    gettimeofday(&end, NULL);
    duration = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
    printf("%f\n", duration);

    gettimeofday(&start, NULL);
    for (int i = 0; i < ow * oh; i++) {
        ConvInt8(packed_input_2 + i * 16 * kw * kh * ic, packed_weight_2, output + 4 * i, 0, 4 *ic / 16, 4, 0);
    }
    gettimeofday(&end, NULL);
    duration = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);
    printf("%f\n", duration);
}
